package com.party.admin.web.aop;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.party.admin.utils.RealmUtils;
import com.party.admin.web.annotation.UserOperate;
import com.party.admin.web.dto.AjaxResult;
import com.party.common.utils.HttpServletRequestUtils;
import com.party.common.utils.StringUtils;
import com.party.common.utils.UUIDUtils;
import com.party.core.model.log.BehaviorType;
import com.party.core.model.log.LogEvent;
import com.party.core.model.member.MemberGroup;
import com.party.core.service.log.ILogEventService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @ClassName UserOperateLogAspect
 * @Description 处理用户操作日志切面
 * @Author yifeng
 * @Date 2019/4/22 11:23
 **/
@Aspect
@Component
public class UserOperateLogAspect {
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private ILogEventService logEventService;

    @AfterReturning(value = "@annotation(com.party.admin.web.annotation.UserOperate) && @annotation(annotation)", returning = "retValue")
    public void interceptorApplogicA(JoinPoint point, UserOperate annotation, Object retValue) {
        try {
            String description = null;
            boolean isSuccess = true;
            if (retValue instanceof AjaxResult) {
                AjaxResult ajaxResult = (AjaxResult) retValue;
                isSuccess = ajaxResult.isSuccess();
                if (!isSuccess) {
                    description = ajaxResult.getDescription();
                }
            }
            if (BehaviorType.LOGIN.getCode().equals(annotation.behaviorType()) && !isSuccess) {
                return;
            }
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            MemberGroup currentUser = RealmUtils.getCurrentUser();
            String ip = HttpServletRequestUtils.getRemoteIpAddress(request);

            String requestURI = request.getRequestURI();
            String requestMethod = request.getMethod();

            String userAgentStr = request.getHeader("User-Agent");

            Map<String, Object> params = Maps.newHashMap();
            Map<String, Object> parameterMap = request.getParameterMap();
            for (Map.Entry<String, Object> entry : parameterMap.entrySet()) {
                if (entry.getValue() instanceof String[]) {
                    String[] values = (String[]) entry.getValue();
                    boolean isEmpty = false;
                    for (String value : values) {
                        if (StringUtils.isEmpty(value)) {
                            isEmpty = true;
                        } else {
                            isEmpty = false;
                        }
                    }
                    if (!isEmpty) {
                        if (BehaviorType.LOGIN.getCode().equals(annotation.behaviorType().getCode()) && isSuccess) {
                            if ("password".equals(entry.getKey())) {
                                continue;
                            }
                        }
                        params.put(entry.getKey(), entry.getValue());
                    }
                } else if (!(entry.getValue() instanceof String[])) {
                    if (null != entry.getValue()) {
                        if (BehaviorType.LOGIN.getCode().equals(annotation.behaviorType().getCode()) && isSuccess) {
                            if ("password".equals(entry.getKey())) {
                                continue;
                            }
                        }
                        params.put(entry.getKey(), entry.getValue());
                    }
                }
            }
            MethodSignature signature = (MethodSignature) point.getSignature();
            String methodName = signature.getMethod().getName();
            String className = point.getTarget().getClass().getName();

            LogEvent logEvent = new LogEvent();
            logEvent.setBehaviorType(annotation.behaviorType().getCode());
            logEvent.setModuleName(annotation.moduleName());
            logEvent.setRequestUrl(requestURI);
            logEvent.setRequestMethod(requestMethod);
            logEvent.setBrowser(HttpServletRequestUtils.getBrowser(userAgentStr));
            logEvent.setOperatSystem(HttpServletRequestUtils.getOs(userAgentStr));
            if (null != currentUser) {
                logEvent.setOperator(currentUser.getRealname());
                logEvent.setOperatorId(currentUser.getId());
            } else {
                logEvent.setOperator("无名");
            }
            logEvent.setType(1);
            logEvent.setRemoteAddr(ip);
            logEvent.setCallerClass(className);
            logEvent.setCallerMethod(methodName);
            logEvent.setArgument(JSONObject.toJSONString(params));
            logEvent.setId(UUIDUtils.generateRandomUUID());
            logEvent.setRemarks(description);
            logEventService.insert(logEvent);
        } catch (Exception e) {
            logger.error("记录操作日志异常", e);
        }
    }
}
